/*
    SUSAN® - Sole of Unix Save ANything

   Copyright (C) 2005-2011 Hechzh Property
      Copyright (C) 2011-2016 Skyatlas Co. LTD

   Copyright (C) 2013-2013 Hechzh Property

   
*/
/*
 * crypto.c Encryption support functions
 *
 * Author: Landon Fuller <landonf@opendarwin.org>
 */

#include "include/susan.h"

/*
 * SUSAN ASN.1 Syntax
 *
 * OID Allocation:
 * Prefix:
 * iso.org.dod.internet.private.enterprise.susan.backup(1.3.6.1.4.1.41093.1)
 * Organization: Hechzh Property
 * Contact Name: Marco van Wieringen
 * Contact E-mail: marco.van.wieringen@skyatlas.net
 *
 * Top Level Allocations - 1
 * 1 - Published Allocations
 *   1.1 - Susan Encryption
 *
 * Susan Encryption - 1.1.1
 * 1 - ASN.1 Modules
 *    1.1 - SusanCrypto
 * 2 - ASN.1 Object Identifiers
 *    2.1 - SignatureData
 *    2.2 - SignerInfo
 *    2.3 - CryptoData
 *    2.4 - RecipientInfo
 *
 * SusanCrypto { iso(1) identified-organization(3) usdod(6)
 *                internet(1) private(4) enterprises(1) susan(41093)
 *                susan(1) published(1) susan-encryption(1)
 *                asn1-modules(1) susan-crypto(1) }
 *
 * DEFINITIONS AUTOMATIC TAGS ::=
 * BEGIN
 *
 * SignatureData ::= SEQUENCE {
 *    version         Version DEFAULT v0,
 *    signerInfo      SignerInfo }
 *
 * CryptoData ::= SEQUENCE {
 *    version                     Version DEFAULT v0,
 *    contentEncryptionAlgorithm  ContentEncryptionAlgorithmIdentifier,
 *    iv                          InitializationVector,
 *    recipientInfo               RecipientInfo
 * }
 *
 * SignerInfo ::= SET OF SignerInfo
 * RecipientInfo ::= SET OF RecipientInfo
 *
 * Version ::= INTEGER { v0(0) }
 *
 * SignerInfo ::= SEQUENCE {
 *    version                 Version,
 *    subjectKeyIdentifier    SubjectKeyIdentifier,
 *    digestAlgorithm         DigestAlgorithmIdentifier,
 *    signatureAlgorithm      SignatureAlgorithmIdentifier,
 *    signature               SignatureValue }
 *
 * RecipientInfo ::= SEQUENCE {
 *    version                 Version
 *    subjectKeyIdentifier    SubjectKeyIdentifier
 *    keyEncryptionAlgorithm  KeyEncryptionAlgorithmIdentifier
 *    encryptedKey            EncryptedKey
 * }
 *
 * SubjectKeyIdentifier ::= OCTET STRING
 *
 * DigestAlgorithmIdentifier ::= AlgorithmIdentifier
 *
 * SignatureAlgorithmIdentifier ::= AlgorithmIdentifier
 *
 * KeyEncryptionAlgorithmIdentifier ::= AlgorithmIdentifier
 *
 * ContentEncryptionAlgorithmIdentifier ::= AlgorithmIdentifier
 *
 * InitializationVector ::= OCTET STRING
 *
 * SignatureValue ::= OCTET STRING
 *
 * EncryptedKey ::= OCTET STRING
 *
 * AlgorithmIdentifier ::= OBJECT IDENTIFIER
 *
 * END
 */

/* Shared Code */

/*
 * Default PEM encryption passphrase callback.
 * Returns an empty password.
 */
int CryptoDefaultPemCallback(char* buf, int size, const void* userdata)
{
  bstrncpy(buf, "", size);
  return (strlen(buf));
}

/*
 * Returns the ASCII name of the digest type.
 * Returns: ASCII name of digest type.
 */
const char* crypto_digest_name(crypto_digest_t type)
{
  switch (type) {
    case CRYPTO_DIGEST_MD5:
      return "MD5";
    case CRYPTO_DIGEST_SHA1:
      return "SHA1";
    case CRYPTO_DIGEST_SHA256:
      return "SHA256";
    case CRYPTO_DIGEST_SHA512:
      return "SHA512";
    case CRYPTO_DIGEST_NONE:
      return "None";
    default:
      return "Invalid Digest Type";
  }
}

/*
 * Given a stream type, returns the associated
 * crypto_digest_t value.
 */
crypto_digest_t CryptoDigestStreamType(int stream)
{
  switch (stream) {
    case STREAM_MD5_DIGEST:
      return CRYPTO_DIGEST_MD5;
    case STREAM_SHA1_DIGEST:
      return CRYPTO_DIGEST_SHA1;
    case STREAM_SHA256_DIGEST:
      return CRYPTO_DIGEST_SHA256;
    case STREAM_SHA512_DIGEST:
      return CRYPTO_DIGEST_SHA512;
    default:
      return CRYPTO_DIGEST_NONE;
  }
}

/*
 *  * Given a crypto_error_t value, return the associated
 *   * error string
 *    */
const char* crypto_strerror(crypto_error_t error)
{
  switch (error) {
    case CRYPTO_ERROR_NONE:
      return _("No error");
    case CRYPTO_ERROR_NOSIGNER:
      return _("Signer not found");
    case CRYPTO_ERROR_NORECIPIENT:
      return _("Recipient not found");
    case CRYPTO_ERROR_INVALID_DIGEST:
      return _("Unsupported digest algorithm");
    case CRYPTO_ERROR_INVALID_CRYPTO:
      return _("Unsupported encryption algorithm");
    case CRYPTO_ERROR_BAD_SIGNATURE:
      return _("Signature is invalid");
    case CRYPTO_ERROR_DECRYPTION:
      return _("Decryption error");
    case CRYPTO_ERROR_INTERNAL:
      /* This shouldn't happen */
      return _("Internal error");
    default:
      return _("Unknown error");
  }
}
